const mysql = require('mysql');
const MysqlConnection = require('./mysql_connection');

class MysqlPool {
    constructor(host,port,user,password,database,cfg=null){
        this.cfgInfo = null;
        if (cfg) {
            this.cfgInfo = cfg;
        } else {
            this.cfgInfo = {
                connectionLimit: 100,
                dateStrings: true,
                multipleStatements:false,
                supportBigNumbers: false,
                bigNumberStrings: false
            }
        }
        this.cfgInfo.host = host;
        this.cfgInfo.port = port;
        this.cfgInfo.user = user;
        this.cfgInfo.password = password;
        this.cfgInfo.database = database;
        this.pool = mysql.createPool(this.cfgInfo);
    }
    printError(err) {
        if (global.log) {
            global.log.error(err);
        } else {
            console.error(err);
        }
    }
    //获取一个连接
    getConnection(){
        let self = this;
        return new Promise(function (resolve, reject) {
            self.pool.getConnection((err, conn)=> {
                if (err) {
                    reject(err);
                } else {
                    resolve(new MysqlConnection(conn));
                }
            });
        })
    }
    //关闭所有连接
    close(){
        let self = this;
        return new Promise(function (resolve, reject) {
            self.pool.end(function(err){
                if (err) {
                    reject(err);
                } else {
                    resolve(null);
                }
            });
        })
    }
    //获取查询结果
    async query(sql, param=null){
        let err = null;
        let ret = null;
        const conn = await this.getConnection();
        try {
            ret = await conn.query(sql, param);
        } catch (error) {
            err = error;
        }
        conn.release();
        if (err) {
            throw err;
        }
        return ret;
    }
    //获取查询结果一行
    async queryOneRow(sql, param=null){
        let err = null;
        let ret = null;
        const conn = await this.getConnection();
        try {
            ret = await conn.query(sql, param, true);
        } catch (error) {
            err = error;
        }
        conn.release();
        if (err) {
            throw err;
        }
        return ret;
    }
    //执行查询不反回结果
    async execute(sql, param=null){
        const conn = await this.getConnection();
        try {
            await conn.execute(sql, param);
        } catch (error) {
            this.printError(error);
        }
        conn.release();
        return null;
    }
    //执行一次事务,回调函数返回true则提交，返回false则回滚
    async transaction(callback){
        let err = null;
        let ret = false;
        const conn = await this.getConnection();
        try {
            await conn.beginTransaction();
            ret = await callback(conn);
            if (ret) {
                await conn.commit();
            } else {
                await conn.rollback();
            }
        } catch (error) {
            err = error;
            await conn.rollback();
        }
        conn.release();
        if (err) {
            throw err;
        }
        return ret;
    }
    //按一次事务查询一组语句,有错误则回滚
    async executeList(sqlArr, paramArr=null){
        let err = null;
        const conn = await this.getConnection();
        try {
            await conn.beginTransaction();
            for (let i = 0; i < sqlArr.length; i++) {
                await conn.execute(sqlArr[i], paramArr?paramArr[i]:null);
            }
            await conn.commit();
        } catch (error) {
            err = error;
            await conn.rollback();
        }
        conn.release();
        if (err) {
            throw err;
        }
        return null;
    }
    //执行一组select语句
    async selectList(sqlArr, paramArr=null){
        let err = null;
        let rets = [];
        const conn = await this.getConnection();
        try {
            for (let i = 0; i < sqlArr.length; i++) {
                const ret = await conn.query(sqlArr[i], paramArr?paramArr[i]:null);
                rets.push(ret);
            }
        } catch (error) {
            err = error;
        }
        conn.release();
        if (err) {
            throw err;
        }
        return rets;
    }
}

module.exports = MysqlPool;
